package main

import (
	"fmt"
	"sync"
	"time"
)

// User 代表一个用户
type User struct {
	ID string
	// 今日剩余票数（会随着定时器自动更新）
	RemainingVotes int
	// 自己收到的票数
	ReceivedVotes int
	mu            sync.Mutex
}

// VoteManager 负责管理投票
type VoteManager struct {
	mu         sync.Mutex
	users      map[string]*User
	dailyLimit int
}

func NewVoteManager(dailyLimit int) *VoteManager {
	vm := &VoteManager{
		users:      make(map[string]*User),
		dailyLimit: dailyLimit,
	}

	// 启动定时器，每天重置投票数
	go func() {
		ticker := time.NewTicker(24 * time.Hour)
		for {
			<-ticker.C
			vm.resetVotes()
		}
	}()

	return vm
}

// resetVotes 重置所有用户的投票数
func (vm *VoteManager) resetVotes() {
	vm.mu.Lock()
	defer vm.mu.Unlock()

	for _, user := range vm.users {
		user.mu.Lock()
		user.RemainingVotes = vm.dailyLimit
		user.mu.Unlock()
	}
	fmt.Println("所有用户的剩余票数已被重置.")
}

// AddUser 添加用户
func (vm *VoteManager) AddUser(userID string) {
	vm.mu.Lock()
	defer vm.mu.Unlock()

	vm.users[userID] = &User{
		ID:             userID,
		RemainingVotes: vm.dailyLimit,
		ReceivedVotes:  0,
	}
}

// GetUser 获取用户
func (vm *VoteManager) GetUser(userID string) (*User, bool) {
	vm.mu.Lock()
	defer vm.mu.Unlock()

	user, exists := vm.users[userID]
	return user, exists
}

// Vote 投票操作
func (u *User) Vote(target *User) bool {
	u.mu.Lock()
	defer u.mu.Unlock()

	if u.RemainingVotes == 0 {
		fmt.Printf("用户编号为 %s 已经没有多余票投给别人了.\n", u.ID)
		return false
	}

	target.mu.Lock()
	defer target.mu.Unlock()

	// 自己剩余票数减一，对方收到的票数加一
	// 如果设计数据库要注意事务
	u.RemainingVotes--
	target.ReceivedVotes++
	fmt.Printf("用户%s投给了用户%s一票，用户%s剩余%d票，用户%s已经拥有%d张选票\n", u.ID, target.ID, u.ID, u.RemainingVotes, target.ID, target.ReceivedVotes)

	return true
}

func main() {
	voteManager := NewVoteManager(5)

	// 添加用户
	voteManager.AddUser("user1")
	voteManager.AddUser("user2")
	voteManager.AddUser("user3")
	voteManager.AddUser("target1")
	voteManager.AddUser("target2")
	voteManager.AddUser("target3")

	// 模拟用户投票
	for i := 0; i < 6; i++ {
		for _, userID := range []string{"user1", "user2", "user3"} {
			for _, targetID := range []string{"target1", "target2", "target3"} {
				user, _ := voteManager.GetUser(userID)
				target, _ := voteManager.GetUser(targetID)
				success := user.Vote(target)
				if !success {
					fmt.Printf("用户 %s 今天不能再投票了.\n", userID)
				}
			}
		}
		time.Sleep(4 * time.Second)
	}
}
